package com.innovation.sys.common.aspect;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;

@Aspect
@Component
public class LogAspect {

	private final Logger logger = LoggerFactory.getLogger(LogAspect.class);

	@Pointcut("execution(* com.innovation.sys.service..*.*(..))")
	private void pointCutMethod() {
	}

	@Before(value = "pointCutMethod() && @annotation(com.innovation.sys.common.annotation.LogAnnotation)")
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void doBefore(JoinPoint joinPoint) {
		// 开始时间。
		long startTime = System.currentTimeMillis();
		Map<String, Object> threadInfo = new HashMap<>();
		threadInfo.put("START_TIME", startTime);
		// 请求参数。
		StringBuilder requestStr = new StringBuilder();
		Object[] args = joinPoint.getArgs();
		if (args != null && args.length > 0) {
			for (Object arg : args) {
				requestStr.append(arg.toString());
			}
		}
		threadInfo.put("REQUEST_PARAMS", requestStr.toString());
		ThreadLocal threadLocal = new ThreadLocal();
		threadLocal.set(threadInfo);
		logger.info("接口开始调用:requestData={}", threadInfo.get("REQUEST_PARAMS"));
	}

	@AfterReturning(value = "pointCutMethod() && @annotation(com.innovation.sys.common.annotation.LogAnnotation)", returning = "res")
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void doAfterReturning(Object res) {
		ThreadLocal threadLocal = new ThreadLocal();
		Map<String, Object> threadInfo = (Map<String, Object>) threadLocal.get();
		long takeTime = 0L;
		if (threadInfo != null) {
			// 结束时间
			takeTime = System.currentTimeMillis()
					- (long) threadInfo.getOrDefault("START_TIME", System.currentTimeMillis());
			logger.info((String) threadInfo.getOrDefault("REQUEST_PARAMS", "") + JSON.toJSONString(res).toString()
					+ takeTime);
		}
		threadLocal.remove();
		logger.info("接口结束调用:耗时={}ms,result={}", takeTime, res);
	}

	@AfterThrowing(value = "pointCutMethod() && @annotation(com.innovation.sys.common.annotation.LogAnnotation)", throwing = "throwable")
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void doAfterThrowing(Throwable throwable) {
		ThreadLocal threadLocal = new ThreadLocal();
		Map<String, Object> threadInfo = (Map<String, Object>) threadLocal.get();
		if (threadInfo != null) {
			logger.info((String) threadInfo.getOrDefault("REQUEST_PARAMS", "") + throwable);
		}
		threadLocal.remove();
		logger.error("error:{}", throwable);
	}

}
